from django.shortcuts import render
from django.http.response import HttpResponseRedirect
from rest_framework import generics, mixins
from rest_framework.views import APIView
from method.tools import Response
from rest_framework import status as status_code
from . import serializers, models
from django.contrib import auth
from method import tools
from method import ac
from method import decorator
from method import email
from method.redis import get_redis_client
from django.conf import settings
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile

try:
    from django.contrib.sessions.models import SessionStore
except ImportError:
    from django.contrib.sessions.backends.db import SessionStore

import xlrd
import traceback
import os
import time
import datetime
import uuid
from tb_forms.functions.log import clog


class MyUpdateModelMixin(object):
    """
    Update a model instance.
    """
    @clog(__name__)
    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        # serializer.is_valid(raise_exception=False)
        self.perform_update(serializer)
        return Response(serializer.data)


    def perform_update(self, serializer):
        serializer.save()

    @clog(__name__)
    def partial_update(self, request, *args, **kwargs):
        kwargs['partial'] = True
        return self.update(request, *args, **kwargs)


class UsersView(generics.ListCreateAPIView):
    queryset = models.MyUser.objects.all()
    serializer_class = serializers.UsersSerializer

    @clog(__name__)
    def get(self, request, *args, **kwargs):
        org_id = request.GET.get("org_id", None)
        if org_id:
            # queryset = [obj.user for obj in models.UserOrgMap.objects.filter(org_id=org_id)]
            # return Response(self.serializer_class(queryset, many=True).data, status=status_code.HTTP_200_OK)
            queryset = models.UserOrgMap.objects.filter(org_id=org_id)
            return Response(serializers.UserOrgRoleSerializer(queryset, many=True).data, status=status_code.HTTP_200_OK)
        else:
            return super(UsersView, self).get(request, *args, **kwargs)

    @clog(__name__)
    def post(self, request, *args, **kwargs):
        try:
            result = super(UsersView, self).post(request, *args, **kwargs)
        except Exception as e:
            result = Response({"message": str(e)}, status=status_code.HTTP_400_BAD_REQUEST)
        return result

    @clog(__name__)
    def put(self, request, *args, **kwargs):  # {"staffid":"['F1330319']"}
        data = tools.is_valid(request, "PUT", "staffid")
        if not isinstance(data, dict):
            return data

        if "staffid" in data:
            if type(data["staffid"]) == str:
                data["staffid"] = eval(data["staffid"])
            queryset = models.MyUser.objects.filter(username__in=data["staffid"])
            result = self.serializer_class(queryset, many=True).data
            if result:
                result = list(result)
            return Response(result)
        else:
            return Response({"status": "False", "msg": "請提供'staffid'數組參數"})

    # def get(self, request, *args, **kwargs):
    #     return self.retrieve(request, *args, **kwargs)

    # def get(self, request, *args, **kwargs):
    #     user = self.get_object()
    #     data = serializers.UsersSerializer(user).data
    #     return Response(data)


class UserView(mixins.RetrieveModelMixin,
               mixins.UpdateModelMixin,
               mixins.DestroyModelMixin,
               generics.ListAPIView):

    def get_serializer_class(self):
        return serializers.UserSerializer


    def get_queryset(self):
        return models.MyUser.objects.all()

    @clog(__name__)
    def get(self, request, *args, **kwargs):
        # user = self.get_object()
        # data = serializers.UserSerializer(user).data
        # return Response(data)
        return super(UserView, self).retrieve(request, *args, **kwargs)

    @clog(__name__)
    def post(self, request, *args, **kwargs):       # 因为APP无法使用PUT方式上传文件，所以把这个POST的接口调给他们，
        return self.put(request, *args, **kwargs)   # 实际POST传过来的值还是调用PUT方法

    @clog(__name__)
    def put(self, request, *args, **kwargs):
        head = request.FILES.get("head")
        sign = request.FILES.get("sign")

        if head:
            # 这是保存文件到本地的方法
            request.data["head"] = ac.handle_image(head, request.user.username,
                                                   settings.MEDIA_ROOT + "head/",
                                                   settings.FILE_ROOT_URL + "head/")

            # 这是保存至文件服务器中的方法
            # suffix = head.name.split(".")[1]        # 取出文件名中的后缀
            # head.name = request.user.username + "." + suffix
            # save_head = tools.save_file("head/", head)
            # request.data["head"] = save_head["path"]
        if sign:
            # 这是保存文件到本地的方法
            request.data["sign"] = ac.handle_image(sign, request.user.username,
                                                   settings.MEDIA_ROOT + "sign/",
                                                   settings.FILE_ROOT_URL + "sign/")

            # 这是保存至文件服务器中的方法
            # suffix = sign.name.split(".")[1]        # 取出文件名中的后缀
            # sign.name = request.user.username + "." + suffix
            # save_sign = tools.save_file("sign/", sign)
            # request.data["sign"] = save_sign["path"]

        return self.update(request, *args, **kwargs)

    @clog(__name__)
    def delete(self, request, *args, **kwargs):
        # return self.destroy(request, *args, **kwargs)
        obj = self.get_object()
        obj.is_active = 0
        obj.status_id = 101
        obj.save()
        return Response({"message": "刪除成功"})


class QueryUserView(generics.ListAPIView):
    serializer_class = serializers.QueryUserSerializer
    queryset = models.MyUser.objects.all()

    @clog(__name__)
    def get(self, request, *args, **kwargs):
        org_id = request.GET.get("org_id", None)
        if org_id:
            result = list()
            for obj in models.UserOrgMap.objects.filter(org_id=org_id):
                user = obj.user
                user.setattr("org", obj.org, None)
                result.append(user)
            return Response(self.serializer_class(result, many=True).data, status=status_code.HTTP_200_OK)
        else:
            return super(QueryUserView, self).get(request, *args, **kwargs)


class Test2(APIView):
    @clog(__name__)
    def get(self, request, *args, **kwargs):
        result = ((1,2,3, ), (4,5,6,))
        return Response(result, status=status_code.HTTP_200_OK)

    @clog(__name__)
    def post(self, request, *args, **kwargs):
        file = request.data['file']
        # print(file)
        return Response(tools.save_file("files/head/", file))


# class StatusView(mixins.RetrieveModelMixin,
#                  generics.ListAPIView):
#     lookup_field = "code"
#     serializer_class = serializers.StatusSerializer
#
#     def get_queryset(self):
#         return models.Status.objects.all()
#
#     def get(self, request, *args, **kwargs):
#         if not kwargs:
#             return Response(self.serializer_class(self.get_queryset(), many=True).data, status=status_code.HTTP_200_OK)
#         else:
#             query = models.Status.objects.filter(status_code=kwargs["code"])
#             return Response(self.serializer_class(query, many=True).data, status=status_code.HTTP_200_OK)


class StatusManyView(generics.ListCreateAPIView):
    serializer_class = serializers.StatusSerializer
    queryset = models.Status.objects.all()


class StatusView(mixins.RetrieveModelMixin,
                 mixins.UpdateModelMixin,
                 mixins.DestroyModelMixin,
                 generics.ListAPIView):
    serializer_class = serializers.StatusSerializer
    queryset = models.Status.objects.all()
    lookup_field = "status_code"

    @clog(__name__)
    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    @clog(__name__)
    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    @clog(__name__)
    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)


class OrgLevelsView(generics.ListCreateAPIView):
    """
    Many org level
    """
    serializer_class = serializers.OrgLevelsSerializer
    queryset = models.OrgLevel.objects.all().order_by("level")

    @clog(__name__)
    def post(self, request, *args, **kwargs):
        obj = models.OrgLevel()
        level = eval(request.data["level"])
        request.data['level'] = obj.get_level(front=level[0], later=level[1])
        return super(OrgLevelsView, self).post(request, *args, **kwargs)


class OrgLevelView(mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   generics.ListAPIView):
    """
    Single org level
    """
    lookup_field = "level"
    serializer_class = serializers.OrgLevelSerializer
    serializer_class.Meta.read_only_fields = ("level", )
    queryset = models.OrgLevel.objects.all().order_by("level")

    @clog(__name__)
    def get(self, request, *args, **kwargs):
        return super(OrgLevelView, self).retrieve(request, *args, **kwargs)

    @clog(__name__)
    def put(self, request, *args, **kwargs):
        # data = tools.is_valid(request, "PUT", "level_name", "level_code", "duty.name")
        # if not isinstance(data, dict):
        #     return data
        # obj = self.get_object()
        # obj.level_name = data["level_name"]
        # obj.level_code = data["level_code"]
        # obj.duty_id = int(data["duty.name"])
        # obj.save(force_update=True, update_fields=('level_name', 'level_code', 'duty_id'))
        # return Response(serializers.OrgLevelSerializer(obj).data, status=status_code.HTTP_202_ACCEPTED)
        return super(OrgLevelView, self).update(request, *args, **kwargs)

    @clog(__name__)
    def delete(self, request, *args, **kwargs):
        return super(OrgLevelView, self).destroy(request, *args, **kwargs)


class OrginazeView(generics.ListCreateAPIView):
    """
    多個的組織架構
    """
    serializer_class = serializers.OrgSerializer
    queryset = models.Org.objects.all().filter(is_active=True).order_by("org_level")

    @clog(__name__)
    @decorator.check_permission(['查看組織'])
    def get(self, request, *args, **kwargs):
        return super(OrginazeView, self).get(request, *args, **kwargs)

    @clog(__name__)
    def post(self, request, *args, **kwargs):
        data = request.data
        serializer = serializers.OrgSerializer(data=data)
        if serializer.is_valid():
            try:
                serializer.save()
                return Response(serializer.data, status=status_code.HTTP_201_CREATED)
            except Exception as e:
                return Response({"message": str(e)}, status=status_code.HTTP_400_BAD_REQUEST)
        return Response(serializer.errors, status=status_code.HTTP_400_BAD_REQUEST)


class OrgView(mixins.UpdateModelMixin,
              mixins.DestroyModelMixin,
              generics.ListAPIView):

    """
    單個組織架構的刪、改操作
    """
    serializer_class = serializers.OrgSerializer
    queryset = models.Org.objects.filter(is_active=True)

    @clog(__name__)
    def get(self, request, *args, **kwargs):
        return Response(serializers.OrgSerializer(self.get_object()).data, status=status_code.HTTP_200_OK)

    @clog(__name__)
    def put(self, request, *args, **kwargs):
        try:
            return self.update(request, *args, **kwargs)
        except Exception as error:
            return Response({"message": str(error)}, status=status_code.HTTP_400_BAD_REQUEST)
        # parent_id = request.data["parent_id"]       # 用户可以通过上传组织代码来修改父节点
        # if not parent_id:
        #     if int(request.data["org_level"]) != settings.MAX_ORG_LEVEL:
        #         return Response({"message": "當前組織級別需要填寫'parent_id'參數！"},
        #                         status=status_code.HTTP_400_BAD_REQUEST)
        # elif not parent_id.isdigit():
        #     query = models.Org.objects.filter(org_code__iexact=parent_id)
        #     if not query:
        #         return Response({"message": "您填的組織代碼'%s'是錯誤的！" % parent_id},
        #                         status=status_code.HTTP_400_BAD_REQUEST)
        #     else:
        #         request.data["parent_id"] = query[0].pk     # 把按组织代码查出来的组织ID重新放入请求中以替换正确的parent_id
        # try:
        #     return self.update(request, *args, **kwargs)
        # except Exception as error:
        #     return Response({"message": str(error)}, status=status_code.HTTP_400_BAD_REQUEST)

    @clog(__name__)
    def delete(self, request, *args, **kwargs):
        obj = self.get_object()
        tree = ac.Tree(obj.id)
        try:
            if obj.org_level == obj.max_org_level:          # 假如待删除的父节点是最大的节点，那么需要跳过内容自检
                tree.handle(obj, max_org=True)
            else:
                tree.handle(obj)
            tree.parse()
        except Exception as error:
            return Response({"message": str(error)}, status=status_code.HTTP_400_BAD_REQUEST)
        for query in tree.list_query:       # 把迭代出来的组织树进行删除操作（修改为未激活状态）
            query.is_active = False
            query.save()
        return Response({"message": "刪除成功!"}, status=status_code.HTTP_200_OK)
        # return self.destroy(request, *args, **kwargs)


class ProjectsView(generics.ListCreateAPIView):
    """
    當獲取數據的格式為JSON時，中文會被轉碼為Unicode編碼
    """

    serializer_class = serializers.ProjectSerializer

    def get_queryset(self):
        return models.Project.objects.filter(status_id=settings.STATUS_ACTIVE["SYSTEM"])

    @clog(__name__)
    @decorator.include_chinese
    def get(self, request, *args, **kwargs):
        app = request.GET.get("app", None)
        if app:
            self.queryset = models.Project.objects.filter(status_id=settings.STATUS_ACTIVE["SYSTEM"], have_app=True)
        else:
            self.queryset = self.get_queryset()

        PIDList = request.GET.get("PIDList", None)
        if PIDList:
            PIDList = eval(PIDList)
            self.queryset = models.Project.objects.filter(
                PID__in=PIDList).filter(status_id=settings.STATUS_ACTIVE["SYSTEM"])
        result = []
        for query in self.queryset:
            data = serializers.ProjectSerializer(query).data
            data["modules"] = query.get_modules()
            result.append(data)
        return result

    @clog(__name__)
    def post(self, request, *args, **kwargs):
        return super(ProjectsView, self).post(request, *args, **kwargs)


class CheckUserView(generics.CreateAPIView):
    """
    GET: 提交用户名(username)，验证工号的有效性，如是否存在，是否在有效期\n
    POST: 提交用戶名(username)和密碼(password)，返回驗證結果，結果不包含用戶信息
    """


    def get_serializer_class(self):
        return serializers.CheckSerializer

    @clog(__name__)
    def get(self, request):
        username = request.GET.get("username", None)

        if not username:
            return Response({"status": "False",
                             "message": "請輸入參數工號或密碼!"},
                            status=status_code.HTTP_200_OK)
        else:
            user_obj = models.MyUser.objects.filter(username__iexact=username)

        if not user_obj:
            return Response({"status": "False",
                             "message": "用戶 '%s' 不存在！" % username},
                            status=status_code.HTTP_200_OK)
        # 暂且不检测用户状态
        # elif user_obj[0].is_active is False or user_obj[0].status_id != settings.STATUS_ACTIVE["USER"]:
        #     return Response({"status": "False",
        #                      "message": "User: '%s' status: %s!" % (username, user_obj[0].status.status_name)},
        #                     status=status_code.HTTP_200_OK)
        else:
            return Response({"status": "True",
                             "message": "用戶正常!", "data": {"id": user_obj[0].pk}},
                            status=status_code.HTTP_200_OK)

    @clog(__name__)
    def post(self, request, *args, **kwargs):
        # username = request.POST.get("username", None)
        # password = request.POST.get("password", None)
        data = tools.is_valid(request, "POST", "username", "password")
        if not isinstance(data, dict):
            return data

        if not data["username"] or not data["password"]:
            return Response({"status": "False", "message": "工號或密碼不能為空!"})

        user_obj = models.MyUser.objects.filter(username__iexact=data["username"])
        if not user_obj:
            msg = "用戶 '%s' 不存在!" % data["username"]
            return Response({"status": "False", "message": msg})
        else:
            user_obj = user_obj[0]

        if user_obj.check_password(data["password"]):
            return Response({
                "status": "True", "message": ""
            })
        else:
            return Response({
                "status": "False", "message": "密碼錯誤!"
            })


class CheckTokenView(APIView):

    def get(self, request, *args, **kwargs):
        try:
            token = request.META["HTTP_X_CSRFTOKEN"]
            token = models.LoginToken.objects.filter(token=token,
                                                     end_date__gte=datetime.datetime.now())
            if not token:
                return Response({"status": "False", "msg": "Token error"})
            user = models.MyUser.objects.filter(username__iexact=token[0].user_id)[0]
            result = ac.user_parser(user)
            # result["X-CSRFToken"] = token
            return Response(result)
        except KeyError:
            return Response({"status": "False", "msg": "請攜帶請求頭參數X-CSRFToken"})


class LoginView(generics.ListAPIView):
    serializer_class = serializers.CheckSerializer
    queryset = models.MyUser.objects.all()

    @clog(__name__)
    def get(self, request, *args, **kwargs):
        return Response({"message": "請輸入用戶名或密碼!"},
                        status=status_code.HTTP_200_OK)
        # obj = models.Role.objects.all()[0]
        # result = {}
        # result["join_date"] = obj.create_date       # .strftime(settings.REST_FRAMEWORK["DATETIME_FORMAT"])
        # result["role_name"] = obj.role_name
        # print(result, 111)
        # return Response(result, status=status_code.HTTP_200_OK)

    @clog(__name__)
    # @csrf_exempt
    def post(self, request, *args, **kwargs):
        next_url = request.GET.get("next", None)
        data = tools.is_valid(request, "POST", "username", "password")
        if not isinstance(data, dict):
            return data

        if request.user:  # 假设用户已登录则先退出
            auth.logout(request)

        user_obj = models.MyUser.objects.filter(username__iexact=data["username"])
        if not user_obj:
            return Response({"status": False, "message": "用戶'%s'不存在！" % data["username"]})

        if user_obj[0].status_id != settings.STATUS_ACTIVE["USER"]:
            return Response({"status": False,
                             "message": "登錄失敗，因為用戶狀態為：%s" % user_obj[0].status.status_name})

        user = auth.authenticate(username=data["username"], password=data["password"])
        if user:
            auth.login(request, user)
            # print(request.META["COOKIES"], "ac")
            # token = request.META["HTTP_COOKIE"][0].split("=")[1]

            token = models.LoginToken.objects.filter(user_id=data["username"],
                                                     end_date__gte=datetime.datetime.now())
            end_date = time.strftime("%Y-%m-%d %H:%M:%S",
                                     time.localtime(int(time.time()) + settings.SESSION_COOKIE_AGE))
            if token:
                token[0].end_date = end_date        # 假如存在，更新Token的有效期
                token[0].save()
                token = token[0].token
            else:
                token = str(uuid.uuid4())
                models.LoginToken.objects.create(
                    user_id=data["username"],
                    token=token,
                    end_date=end_date
                )

                # username = request.session.get("username")
            models.LoginToken.objects.filter(user_id=data["username"],
                                             end_date__lte=datetime.datetime.now()).delete()     # 清除用户过期的Token

            result = ac.user_parser(user)
            result["X-CSRFToken"] = token
            if next_url:
                return HttpResponseRedirect(next_url)
            response = Response(result)
            return response
        else:
            return Response({"status": False, "message": "密碼錯誤!"})


class LogoutView(APIView):
    @clog(__name__)
    def get(self, request):
        auth.logout(request)
        if request.COOKIES:
            if "HTTP_X_CSRFTOKEN" in request.META:
                token = request.META["HTTP_X_CSRFTOKEN"]
                models.LoginToken.objects.filter(token=token).delete()
            request.COOKIES = {}
        return Response({"message": "登出成功!"}, status=status_code.HTTP_200_OK)
        # else:
        #     return Response({"message": "Not login!"}, status=status_code.HTTP_200_OK)


class UserOrgsView(generics.ListCreateAPIView):
    serializer_class = serializers.UserOrgSerializer


    def get_queryset(self):
        return models.UserOrgMap.objects.all()

    @clog(__name__)
    def get(self, request, *args, **kwargs):
        return super(UserOrgsView, self).get(request, *args, **kwargs)

    @clog(__name__)
    def post(self, request, *args, **kwargs):
        try:
            result = super(UserOrgsView, self).post(request, *args, **kwargs)
        except Exception as error:
            result = Response({"message": str(error)}, status=status_code.HTTP_400_BAD_REQUEST)
        return result


class UserOrgView(mixins.RetrieveModelMixin,
                  mixins.UpdateModelMixin,
                  mixins.DestroyModelMixin,
                  generics.ListAPIView):

    """
    pass
    """
    serializer_class = serializers.UserOrgSerializer
    queryset = models.UserOrgMap.objects.all()
    lookup_field = 'user_id'

    @clog(__name__)
    def get(self, request, *args, **kwargs):
        self.queryset = models.UserOrgMap.objects.filter(user_id=kwargs['user_id'], org_id=kwargs['org_id'])
        # return Response(self.serializer_class(self.queryset, many=True).data,
        #                 status=status_code.HTTP_200_OK)
        return super(UserOrgView, self).retrieve(request, *args, **kwargs)

    @clog(__name__)
    def put(self, request, *args, **kwargs):
        self.queryset = models.UserOrgMap.objects.filter(user_id=kwargs['user_id'], org_id=kwargs['org_id'])
        return self.update(request, *args, **kwargs)

    @clog(__name__)
    def delete(self, request, *args, **kwargs):
        self.queryset = models.UserOrgMap.objects.filter(user_id=kwargs['user_id'], org_id=kwargs['org_id'])
        return self.destroy(request, *args, **kwargs)


class SitesView(generics.ListCreateAPIView):
    serializer_class = serializers.SiteSerializer
    queryset = models.Site.objects.all()


class SiteView(mixins.RetrieveModelMixin,
               mixins.UpdateModelMixin,
               mixins.DestroyModelMixin,
               generics.ListAPIView):
    serializer_class = serializers.SiteSerializer
    queryset = models.Site.objects.all()

    @clog(__name__)
    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    @clog(__name__)
    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    @clog(__name__)
    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)


class DutysView(generics.ListCreateAPIView):
    serializer_class = serializers.DutySerializer
    queryset = models.Duty.objects.all()


class DutyView(mixins.RetrieveModelMixin,
               mixins.UpdateModelMixin,
               mixins.DestroyModelMixin,
               generics.ListAPIView):
    serializer_class = serializers.DutySerializer
    queryset = models.Duty.objects.all()

    @clog(__name__)
    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    @clog(__name__)
    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    @clog(__name__)
    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)


class OrgRolesView(generics.ListCreateAPIView):
    serializer_class = serializers.OrgRoleSerializer
    queryset = models.OrgRole.objects.all()


class OrgRoleView(mixins.RetrieveModelMixin,
                  mixins.UpdateModelMixin,
                  mixins.DestroyModelMixin,
                  generics.ListAPIView):
    serializer_class = serializers.OrgRoleSerializer
    queryset = models.OrgRole.objects.all()

    @clog(__name__)
    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    @clog(__name__)
    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    @clog(__name__)
    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)


class BulkImportView(generics.ListCreateAPIView):
    serializer_class = serializers.BulkSerializer
    queryset = []

    @clog(__name__)
    def get(self, request, *args, **kwargs):
        # return super(BulkImportView, self).get(request, *args, **kwargs)
        host = request.META["HTTP_HOST"]
        return Response({"人員和組織批量導入格式範本": "http://" + host + "/files/file/user_org.xlsx",
                          "人員的角色批量導入格式範本": "http://" + host + "/files/file/user_role.xlsx",
                          "組織級別批量導入格式範本": "http://" + host + "/files/file/org_level.xlsx"})

    @clog(__name__)
    def post(self, request, *args, **kwargs):
        data = tools.is_valid(request, "POST", 'file', 'select')
        if not isinstance(data, dict):
            return data
        path = default_storage.save(settings.MEDIA_ROOT + "temp/" + data['file'].name,
                                    ContentFile(data['file'].read()))  # 保存文件
        tmp_file = os.path.join(settings.MEDIA_ROOT + "temp/", path)  # 获得文件路径
        open_status, open_data = self.open_excel(tmp_file, 'nrows')

        if data['select'] == "user_org":
            result = self.bulk_user_org(open_data)
            # print(open_data)
            return Response(result, status=status_code.HTTP_200_OK)
        elif data['select'] == "org_level":         # 批量创建组织级别
            result = self.bulk_org_level(open_data)
            return Response(result, status=status_code.HTTP_200_OK)
        elif data['select'] == "user_role":         # 批量添加用戶的角色
            result = self.bulk_user_role(open_data[1:])
            return Response(result, status=status_code.HTTP_200_OK)
        else:
            return Response({"message": "請輸入參數'select'!"}, status=status_code.HTTP_400_BAD_REQUEST)


    def open_excel(self, path, way, sheet=0):
        try:
            data = xlrd.open_workbook(path) #打开Excel文件
            table = data.sheets()[sheet]    # 打开第sheet张表
            if way == "nrows":      # 按行获取
                nrows = table.nrows         # 获取表的行数
                result = []
                for i in range(nrows):      # 循环逐行打印
                    # if i == 0:              # 跳过第一行
                    #     continue
                    # elif i == 1:            # 第二行的是键名
                    #     pass
                    value = table.row_values(i)[1:]     # 取出除第一列外的数据
                    result.append(value)
                return True, result
            elif way == "ncols":     # 按列获取
                ncols = table.ncols  # 获取表的行数
                result = []
                for i in range(ncols):  # 循环逐行打印
                    if i == 0:  # 跳过第一行
                        continue
                    elif i == 1:  # 第二行的是键名
                        pass
                    value = table.row_values(i)[1:]  # 取出除第一列外的数据
                    result.append(value)
                return True, result
        except:
            traceback.print_exc()
            return False, "Open excel error!"
        finally:
            if os.path.exists(path):    # 去除所存储的临时文件
                os.remove(path)


    def bulk_org_level(self, data):
        data = data.pop(0)
        result = {"create": [], "exist": []}
        try:
            for value in data:
                check = models.OrgLevel.objects.filter(level_name=value[0])
                if check:
                    result["exist"].append(check[0].level_name)
                    continue
                else:
                    ol = models.OrgLevel()
                    ol.level = ol.get_new_level()
                    ol.level_name = value[0]
                    ol.level_code = value[1]
                    ol.save()
                    result["create"].append(ol.level_name)
            return result
        except Exception as e:
            return {"message": str(e)}


    def bulk_user_org(self, data):
        result = {"create": [], "exist": [], "error": []}
        keys = data[0][7:]
        self.level_obj_list = [self.check_org_level(level) for level in keys]       # 获取级别对象列表
        data.pop(0)
        for value in data:
            # value: 这个参数就是一行完整的Excel数据
            try:
                user = models.MyUser.objects.filter(username__iexact=value[0])
                if user:           # 假如用戶已經存在的情况
                    user = user[0]
                    result["exist"].append(user.username + "-" + user.last_name)
                else:
                    if value[3] != "無" and value[3]:        # 如果用戶的管理職不為空，那麼就獲取或者創建
                        duty, duty_status = models.Duty.objects.get_or_create(name=value[3])
                    else:                                    # 為空那麼就是員工
                        duty = models.Duty.objects.filter(name=settings.BULK_IMPORT_FIELDS["DUTY"])[0]

                    if not value[5]:                         # 如果廠區為空，那麼給予設置的廠區默認值
                        value[5] = settings.DEFAULT_SITE
                    site, site_status = models.Site.objects.get_or_create(site_name=value[5], site_code=value[5])

                    # 先檢查是否有給定默認密碼值，沒有則設置工號為默認密碼
                    password = settings.BULK_IMPORT_FIELDS["PASSWORD"] \
                               and\
                               settings.BULK_IMPORT_FIELDS["PASSWORD"] \
                               or\
                               value[0]             # 有默認密碼則設置默認值，沒有就設置工號

                    user = models.MyUser()          # 其他的
                    user.username = value[0]
                    user.last_name = value[1]
                    user.email = value[2] and value[2] or settings.BULK_IMPORT_FIELDS["EMAIL"]
                    user.duty = duty
                    user.site = site
                    user.entry_date = settings.BULK_IMPORT_FIELDS["ENTRY_DATE"]
                    user.sex = settings.BULK_IMPORT_FIELDS["SEX"]
                    user.status_id = settings.BULK_IMPORT_FIELDS["USER_STATUS_ID"]
                    user.set_password(password)
                    user.save()
                    result["create"].append(user.username + "-" + user.last_name)

                self.max_org = models.Org.objects.filter(org_name=settings.BULK_IMPORT_FIELDS["MAX_ORG_NAME"])[0]
                self.check_org(value[7:], value[4])         # 没有组织会创建新的，并不断更新self.max_org

                self.check_user_org_map(user, self.max_org, value[6])
            except Exception as e:
                result["error"].append([value[0] + "-" + value[1], str(e)])
        return result

    def check_org(self, org_list, org_code):
        for index, org_name in enumerate(org_list):
            if org_name == "-" or org_name == "":
                continue
            org = models.Org.objects.filter(org_name=org_name, parent_id=self.max_org.pk)
            if not org:                         # 假如組織不存在，那麼創建新的
                o = models.Org()
                o.org_name = org_name
                o.parent_id = self.max_org.pk
                o.org_code = org_code
                o.org_level = self.level_obj_list[index]
                o.is_active = settings.BULK_IMPORT_FIELDS["ORG_STATUS"]
                o.save()
                self.max_org = o
            else:                               # 假如存在，則把最大組織設定為查到的組織，防止下一個組織需要創建
                self.max_org = org[0]

    def check_org_level(self, level_name):          # 根据提供的组织级别名返回相应的级别对象
        org_level = models.OrgLevel()
        check_level = org_level.check_level(level_name=level_name)
        if not check_level:
            org_level.level = org_level.get_new_level()
            org_level.level_name = level_name
            org_level.level_code = level_name
            org_level.save()
            return org_level
        else:
            return check_level[0]

    def check_user_org_map(self, user_obj, org_obj, org_role):
        check_obj = models.UserOrgMap.objects.filter(user=user_obj, org=org_obj)
        if check_obj:
            return check_obj[0]
        else:
            return models.UserOrgMap.objects.create(
                user=user_obj,
                org=org_obj,
                org_role=self.check_org_role(org_role)
            )

    def check_org_role(self, role_name):
        check_query = models.OrgRole.objects.filter(name=role_name)
        if check_query:
            return check_query[0]
        else:
            return models.OrgRole.objects.filter(name="成員")[0]        # 默認沒有組織角色的時候賦予成員的角色


    def bulk_user_role(self, data):
        """
        批量为用户添加角色
        :param data:    [['F1330319', '黃明星', '系統管理員'], ['F1330320', '黃明星', '系統管理員'],...]
        :return:
        """
        exist, succeed, error = [], [], []
        for single in data:
            try:
                user_obj = models.MyUser.objects.filter(username__iexact=single[0])
                role_obj = models.Role.objects.filter(role_name__iexact=single[2])

                if not user_obj:
                    error.append("用戶'%s'不存在" % single[0])
                    continue
                elif not role_obj:
                    error.append("角色'%s'不存在" % single[2])
                    continue

                result, status = models.UserRoleMap.objects.get_or_create(
                    user=user_obj[0],
                    role=role_obj[0]
                )
                if status:
                    succeed.append("用戶'%s-%s'新增角色'%s'" % tuple(single))
                else:
                    exist.append("用戶'%s-%s'已經擁有角色'%s'" % tuple(single))
            except Exception as e:
                error.append("給用戶'%s'添加角色'%s'錯誤，錯誤原因'%s'" % (single[0], single[2], str(e)))

        return {"succeed": succeed, "exist": exist, "error": error}


def only_username_login(request, user_obj):
    user_obj.backend = auth._get_backends(return_tuples=True)[0][1]
    session = SessionStore()
    request.COOKIES[settings.SESSION_COOKIE_NAME] = session._get_new_session_key()
    if not hasattr(request, "session"):
        request.session = session
    auth.login(request, user_obj)
    return request


class QRCodeLoginView(generics.ListCreateAPIView):
    serializer_class = serializers.LoginQRCodeSerializer
    queryset = models.MyUser.objects.all()

    @clog(__name__)
    def get(self, request, *args, **kwargs):
        return Response({"message": "請輸入對應的參數'uid'或'username'!"},
                        status=status_code.HTTP_200_OK)

    # def post(self, request, *args, **kwargs):
    #     data = tools.is_valid(request, "POST", "uid", "username", "type")
    #     if not isinstance(data, dict):
    #         return data
    #     # os = request.META["HTTP_USER_AGENT"].split("(")[1].split(")")[0]
    #     if data["type"] == "web":
    #         try:
    #             code_obj = models.QRCode.objects.filter(uid__iexact=data["uid"], username__iexact=data["username"])
    #             if code_obj:
    #                 code_obj = code_obj[0]
    #                 user_obj = models.MyUser.objects.filter(username__iexact=code_obj.username)
    #                 if not user_obj:
    #                     return Response({"message": "user '%s' dose not exist!" % code_obj.username})
    #                 result = ac.user_parser(user_obj[0])
    #                 code_obj.delete()
    #                 return Response(result, status=status_code.HTTP_200_OK)
    #             else:
    #                 return Response({"message": "Input error!"}, status=status_code.HTTP_400_BAD_REQUEST)
    #         except Exception as e:
    #             return Response({"message": str(e)}, status=status_code.HTTP_400_BAD_REQUEST)
    #     elif data["type"] == "app":
    #         try:
    #             query = models.QRCode.objects.create(uid=data["uid"], username=data["username"])
    #
    #             if query:
    #                 return Response(
    #                     {"uid": data["uid"], "username": data["username"]},
    #                     status=status_code.HTTP_201_CREATED
    #                 )
    #             else:
    #                 return Response({"message": "Not found!"}, status=status_code.HTTP_400_BAD_REQUEST)
    #         except Exception as e:
    #             return Response({"message": str(e)}, status=status_code.HTTP_400_BAD_REQUEST)
    @clog(__name__)
    # @csrf_exempt
    def post(self, request, *args, **kwargs):
        data = tools.is_valid(request, "POST", "uid", "username", "type")
        if not isinstance(data, dict):
            return data
        # os = request.META["HTTP_USER_AGENT"].split("(")[1].split(")")[0]
        if data["type"] == "web":
            try:
                if request.user.is_authenticated():
                    auth.logout(request)

                code_obj = models.QRCode.objects.filter(uid__iexact=data["uid"],
                                                        username__iexact=data["username"])
                if code_obj:
                    code_obj = code_obj[0]
                    user_obj = models.MyUser.objects.filter(username__iexact=code_obj.username)
                    if not user_obj:
                        return Response({"message": "用戶 '%s' 不存在!" % code_obj.username})
                    user_obj = user_obj[0]
                    result = ac.user_parser(user_obj)

                    only_username_login(request, user_obj)

                    code_obj.delete()         # 验证通过删除数据库中的记录
                    responseSession = str(uuid.uuid4())
                    end_date = time.strftime("%Y-%m-%d %H:%M:%S",
                                             time.localtime(int(time.time()) + settings.SESSION_COOKIE_AGE))
                    models.LoginToken.objects.create(
                        user_id=data["username"],
                        token=responseSession,
                        end_date=end_date
                    )
                    result["X-CSRFToken"] = responseSession
                    return Response(result, status=status_code.HTTP_200_OK)
                else:
                    return Response({"message": "Input error!"}, status=status_code.HTTP_400_BAD_REQUEST)
            except Exception as e:
                return Response({"message": str(e)}, status=status_code.HTTP_400_BAD_REQUEST)
        elif data["type"] == "app":
            try:
                query = models.QRCode.objects.create(uid=data["uid"], username=data["username"])

                if query:
                    return Response(
                        {"uid": data["uid"], "username": data["username"]},
                        status=status_code.HTTP_201_CREATED
                    )
                else:
                    return Response({"message": "未找到響應的數據!"}, status=status_code.HTTP_400_BAD_REQUEST)
            except Exception as e:
                return Response({"message": str(e)}, status=status_code.HTTP_400_BAD_REQUEST)


class RetrievePWDView(generics.ListAPIView):
    serializer_class = serializers.RetrievePWDSerializer

    @clog(__name__)
    def get(self, request, *args, **kwargs):
        return Response({"message": "沒有數據!"}, status=status_code.HTTP_200_OK)

    @clog(__name__)
    def post(self, request, *args, **kwargs):
        data = tools.is_valid(request, "POST", "username", "email")
        if not isinstance(data, dict):
            return data

        queryset = models.MyUser.objects.filter(username=data["username"])
        if queryset:
            queryset = queryset[0]
            if data["email"] == queryset.email:
                code = tools.randoms(6)
                # request.session["check_code"] = code
                # request.session["username"] = data["username"]
                red = get_redis_client()
                desc = request.META["REMOTE_ADDR"] + "-"
                red.set(settings.REDIS_HEAD_SEQ + desc + "check_code", code, settings.SESSION_COOKIE_AGE)
                red.set(settings.REDIS_HEAD_SEQ + desc + "username", data["username"], settings.SESSION_COOKIE_AGE)

                email.sendMail(queryset.email, "密碼找回驗證碼（基準烽火雲台）", code)
                return Response({"message": "Send successfully!"}, status=status_code.HTTP_200_OK)
            else:
                return Response({"message": "不正確的電子郵箱地址或賬號和郵箱不匹配!"},
                                status=status_code.HTTP_400_BAD_REQUEST)
        else:
            return Response({"message": "用戶名錯誤!"}, status=status_code.HTTP_200_OK)


class SetNewPWDView(generics.ListAPIView):
    serializer_class = serializers.SetNewPWDSerializer

    @clog(__name__)
    def get(self, request, *args, **kwargs):
        return Response({"message": "沒有數據!"}, status=status_code.HTTP_200_OK)

    @clog(__name__)
    def post(self, request, *args, **kwargs):
        try:
            desc = request.META["REMOTE_ADDR"] + "-"
            red = get_redis_client()
            check_code = red.get(settings.REDIS_HEAD_SEQ + desc + "check_code")
            username = red.get(settings.REDIS_HEAD_SEQ + desc + "username")
            # check_code = request.session["check_code"]
            # username = request.session["username"]
        except KeyError:
            return Response({"message": "Session參數出現了錯誤!"}, status=status_code.HTTP_400_BAD_REQUEST)

        # data = tools.is_valid(request, "POST", "check_code", "new_pwd")
        # if not isinstance(data, dict):
        #     return data

        post_code = request.POST.get("check_code", None)
        post_pwd = request.POST.get("new_pwd", None)

        if check_code != post_code:
            return Response({"message": "驗證碼錯誤!"}, status=status_code.HTTP_400_BAD_REQUEST)

        if not post_pwd:                # 单独验证验证码的请求
            return Response({"message": "驗證碼驗證通過!"}, status=status_code.HTTP_200_OK)

        user_obj = models.MyUser.objects.filter(username__iexact=username)[0]
        user_obj.set_password(post_pwd)
        user_obj.save()

        red.delete(desc + "check_code")
        red.delete(desc + "username")
        # del request.session["check_code"]
        # del request.session["username"]
        return Response({"message": "密碼修改成功!"}, status=status_code.HTTP_200_OK)


class ActiveUserView(generics.ListAPIView):
    """
    激活用戶接口
    """
    serializer_class = serializers.ActiveUserSerializer


    def get_queryset(self):
        pass

    @clog(__name__)
    def get(self, request, *args, **kwargs):
        return Response({"message": "未找到!"}, status=status_code.HTTP_200_OK)

    @clog(__name__)
    def put(self, request, *args, **kwargs):
        data = tools.is_valid(request, "PUT", "user_id", "status_id")
        if not isinstance(data, dict):
            return data

        data["status_id"] = int(data["status_id"])
        user = models.MyUser.objects.filter(pk=data["user_id"])[0]
        if user.status_id != data["status_id"]:
            user.status_id = data["status_id"]
            user.save(force_update=True, update_fields=("status",))

        return Response({"message": "狀態變更成功！"}, status=status_code.HTTP_200_OK)


class UpdatePWDView(generics.ListAPIView):
    serializer_class = serializers.UpdatePWDSerializer

    def get_queryset(self):
        pass

    @clog(__name__)
    def post(self, request, *args, **kwargs):
        data = tools.is_valid(request, "POST", "username", "old_pwd", "new_pwd")
        if not isinstance(data, dict):
            return data

        user = models.MyUser.objects.filter(username=data["username"])
        if not user:
            return Response({"message": "工號錯誤！"}, status=status_code.HTTP_202_ACCEPTED)

        check_user = auth.authenticate(username=data["username"], password=data["old_pwd"])
        if check_user:
            check_user.password = data["new_pwd"]
            try:
                check_user.save()
            except AssertionError as error:
                return Response({"message": str(error)}, status=status_code.HTTP_202_ACCEPTED)
            return Response({"message": "修改成功！"}, status=status_code.HTTP_200_OK)
        else:
            return Response({"message": "賬號舊密碼錯誤！"}, status=status_code.HTTP_202_ACCEPTED)


